home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / DOCVIEW.PAK / ODLISTVW.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  11KB  |  452 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1993, 1995 by Borland International, All Rights Reserved
  4. //
  5. //   Implements class TODListView
  6. //----------------------------------------------------------------------------
  7. #include <owl/pch.h>
  8. #include <owl/docmanag.h>
  9. #include <owl/filedoc.h>
  10. #include <owl/inputdia.h>
  11. #include <stdio.h>
  12. #include "odlistbx.h"
  13. #include "odlistvw.rc"
  14.  
  15. // class TODListView
  16. // ~~~~~ ~~~~~~~~~~~
  17. class _DOCVIEWCLASS TODListView : public TODListBox, public TView {
  18.   public:
  19.     TODListView(TDocument& doc, TWindow* parent = 0);
  20.    ~TODListView();
  21.     static const char far* StaticName() {return "OD List View";}  // put in resource
  22.     bool DirtyFlag;
  23.  
  24.     // Overridden virtuals from TView
  25.     //
  26.     const char far*  GetViewName() {return StaticName();}
  27.     TWindow* GetWindow()  {return (TWindow*)this;}
  28.     bool     SetDocTitle(const char far* docname, int index)
  29.                           {return TODListBox::SetDocTitle(docname, index); }
  30.     // Overridden virtuals from TWindow
  31.     //
  32.     bool Create();
  33.     uint EvGetDlgCode(MSG far*);
  34.     bool CanClose()   {return TODListBox::CanClose() && Doc->CanClose();}
  35.  
  36.   protected:
  37.     long Origin;
  38.     bool LoadData(int top, int sel);
  39.  
  40.     // Message response functions
  41.     //
  42.     void CmEditUndo();
  43.     void CmEditCut();
  44.     void CmEditCopy();
  45.     void CmEditPaste();
  46.     void CmEditDelete();
  47.     void CmEditClear();
  48.     void CmEditAdd();
  49.     void CmEditItem();
  50. //  void CmLineIndent();
  51. //  void CmLineUnindent();
  52.     bool VnCommit(bool force);
  53.     bool VnRevert(bool clear);
  54.     bool VnIsWindow(HWND hWnd) {return GetHandle() == hWnd;}
  55.     bool VnIsDirty()  {return DirtyFlag;}
  56.     bool VnDocClosed(int omode);
  57.     void EvDestroy();
  58.     void CmSelChange() {} // to prevent interpreting as unprocessed accelerator
  59.  
  60.   DECLARE_RESPONSE_TABLE(TODListView);
  61.   DECLARE_STREAMABLE(,TODListView,1);
  62. };
  63.  
  64.  
  65. //
  66. // Last virtual line appended to list
  67. //
  68. const char VirtualLastLineStr[] = "---";
  69.  
  70. DEFINE_RESPONSE_TABLE1(TODListView, TODListBox)
  71.   EV_COMMAND(CM_ODLISTUNDO,    CmEditUndo),
  72.   EV_COMMAND(CM_ODLISTCUT,     CmEditCut),
  73.   EV_COMMAND(CM_ODLISTCOPY,    CmEditCopy),
  74.   EV_COMMAND(CM_ODLISTPASTE,   CmEditPaste),
  75.   EV_COMMAND(CM_ODLISTCLEAR,   CmEditClear),
  76.   EV_COMMAND(CM_ODLISTDELETE,  CmEditDelete),
  77.   EV_COMMAND(CM_ODLISTADD,     CmEditAdd),
  78.   EV_COMMAND(CM_ODLISTEDIT,    CmEditItem),
  79.   EV_WM_GETDLGCODE,
  80.   EV_WM_DESTROY,
  81.   EV_NOTIFY_AT_CHILD(LBN_DBLCLK,    CmEditItem),
  82.   EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange),
  83.   EV_VN_DOCCLOSED,
  84.   EV_VN_ISWINDOW,
  85.   EV_VN_ISDIRTY,
  86.   EV_VN_COMMIT,
  87.   EV_VN_REVERT,
  88. END_RESPONSE_TABLE;
  89.  
  90. DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TODListView, ODLBTemplate);
  91. ODLBTemplate odBinTpl("ODListBox, All files","*.*", 0, "TXT",dtAutoDelete);
  92. ODLBTemplate odTxtTpl("ODStrings, All files","*.*", 0, "TXT",dtAutoDelete);
  93.  
  94. TODListView::TODListView(TDocument& doc, TWindow* /*parent*/)
  95. :
  96.   TView(doc),
  97.   TODListBox((int)GetNextViewId()),
  98.   Origin(0),
  99.   DirtyFlag(false)
  100. {
  101.   Attr.Style &= ~(WS_BORDER | LBS_SORT);
  102.   Attr.Style |= (WS_HSCROLL | LBS_NOINTEGRALHEIGHT);
  103.   if (doc.GetTemplate() == &odTxtTpl)
  104.     Attr.Style |= LBS_HASSTRINGS;
  105.   Attr.AccelTable = IDA_ODLISTVIEW;
  106.   SetViewMenu(new TMenuDescr(IDM_ODLISTVIEW,0,1,0,0,0,1));
  107. }
  108.  
  109. bool
  110. TODListView::LoadData(int top, int sel)
  111. {
  112.   CmEditClear();
  113.   DeleteString(0);
  114.   DirtyFlag = false;
  115.  
  116.   istream* inStream;
  117.   if ((inStream = Doc->InStream(ios::in)) == 0)
  118.     return false;
  119.  
  120.   for (;;) {
  121.     char buf[100+1];
  122.     inStream->getline(buf, sizeof(buf)-1);
  123.     if (!inStream->gcount() && !inStream->good())
  124.       break;  // if EOF or error
  125.     char* str;
  126.     if (Attr.Style & LBS_HASSTRINGS) {   // strings stored in list box
  127.       str = buf;
  128.     }
  129.     else {
  130.       str = new char[strlen(buf)+1];
  131.       strcpy(str, buf);
  132.     }
  133.     AddString(str);
  134.   }
  135.   AddString(VirtualLastLineStr);
  136.   SetSelIndex(top);
  137.   SetSelIndex(sel);
  138.   delete inStream;   // close file in case process switch
  139.   return true;
  140. }
  141.  
  142. bool
  143. TODListView::Create()
  144. {
  145.   DirtyFlag = false;
  146.   TODListBox::Create();   // throws exception TXInvalidWindow
  147.   if (Doc->GetDocPath() == 0) {
  148.     CmEditClear();         // perform any clearing initialization
  149.     return true;           // new file, no data to display
  150.   }
  151.   if (!LoadData(0, 0))
  152.     NotOK();
  153.   return true;
  154. }
  155.  
  156. bool
  157. TODListView::VnDocClosed(int omode)
  158. {
  159.   int top;
  160.   int sel;
  161.   if (DirtyFlag == 2 || !(omode & ofWrite))  // make sure someone else's write
  162.     return false;
  163.   top = GetTopIndex();
  164.   sel = GetSelIndex();
  165.   LoadData(top, sel);
  166.   return true;
  167. }
  168.  
  169. bool
  170. TODListView::VnCommit(bool force)
  171. {
  172.   if (!force && !DirtyFlag)
  173.     return true;
  174.  
  175.   ostream* outStream;
  176.   if ((outStream = Doc->OutStream(ios::out)) == 0)
  177.     return false;
  178.   outStream->seekp(Origin);
  179.  
  180.   char* buf = 0;  // initialized only to prevent warning about use before def
  181.   int buflen = 0;
  182.   int count = GetCount();
  183.   for (int index = 0; index < count-1; index++) {  // don't write last virtual line
  184.     int len;
  185.     char far* str;
  186.     if (Attr.Style & LBS_HASSTRINGS) {
  187.       len = GetStringLen(index);
  188.     }
  189.     else {
  190.       str = (char far*)GetItemData(index);
  191.       len = str ? strlen(str) : 0;
  192.     }
  193.     if (len != 0) {
  194.       if (len >= buflen) {
  195.         if (buflen != 0)
  196.           delete buf;
  197.         buf = new char[buflen = len+1];
  198.       }
  199.       if (Attr.Style & LBS_HASSTRINGS)
  200.         GetString(buf, index);
  201.       else
  202.         strcpy(buf, str);
  203.       *outStream << buf;
  204.     }
  205.     *outStream << '\n';
  206.   }
  207.   if (buflen != 0)
  208.     delete buf;
  209.   DirtyFlag = 2;           // to detect our own close notification
  210.   delete outStream;
  211.   DirtyFlag = false;
  212.   return true;
  213. }
  214.  
  215. bool
  216. TODListView::VnRevert(bool clear)
  217. {
  218.   if (!clear && Doc->GetDocPath() != 0)
  219.     return LoadData(0,0);
  220.   CmEditClear();
  221.   DirtyFlag = false;
  222.   return true;
  223. }
  224.  
  225. uint
  226. TODListView::EvGetDlgCode(MSG far*)
  227. {
  228.   uint retVal = (uint)DefaultProcessing();
  229.   retVal |= DLGC_WANTCHARS;
  230.   return retVal;
  231. }
  232.  
  233. void
  234. TODListView::CmEditUndo()
  235. {
  236.   MessageBox("Feature not implemented", "Undo", MB_OK);
  237. }
  238.  
  239. void
  240. TODListView::CmEditCut()
  241. {
  242.   CmEditCopy();
  243.   CmEditDelete();
  244. }
  245.  
  246. void
  247. TODListView::CmEditCopy()
  248. {
  249.   int index = GetSelIndex();
  250.   int count = GetCount();
  251.   if (count <= 1 || index >= count-1)
  252.     return;
  253.  
  254.   char far* str;
  255.   int len;
  256.   if (Attr.Style & LBS_HASSTRINGS) {  // strings stored in list box
  257.     len = GetStringLen(index);
  258.   }
  259.   else {
  260.     str = (char far*)GetItemData(index);
  261.     len = strlen(str);
  262.   }
  263.  
  264.   TClipboard cb(*this);
  265.   if (cb.EmptyClipboard()) {
  266.     HANDLE cbhdl = ::GlobalAlloc(GHND, len+0+1);
  267.     char far* gbuf = (char far*)::GlobalLock(cbhdl);
  268.     if (Attr.Style & LBS_HASSTRINGS) {  // strings stored in list box
  269.       GetString(gbuf, index);
  270.     }
  271.     else {
  272.       strcpy(gbuf, str);
  273.     }
  274.     ::GlobalUnlock(cbhdl);
  275.     cb.SetClipboardData(CF_TEXT, cbhdl);
  276.   }
  277. }
  278.  
  279. void
  280. TODListView::CmEditPaste()
  281. {
  282.   int index = GetSelIndex();
  283.   if (index < 0)
  284.     index = 0;
  285.  
  286.   TClipboard cb(*this);
  287.   if (!cb)
  288.     return;  // clipboard open by another window
  289.  
  290.   HANDLE cbhdl = cb.GetClipboardData(CF_TEXT);
  291.   if (cbhdl) {
  292.     char far* text = (char far*)::GlobalLock(cbhdl);
  293.     char far* str;
  294.     if (Attr.Style & LBS_HASSTRINGS) {   // strings stored in list box
  295.       str = text;
  296.     }
  297.     else {
  298.       str = new char[strlen(text)+1];
  299.       strcpy(str, text);
  300.     }
  301.     InsertString(str, index);
  302.     SetSelIndex(index+1);
  303.     DirtyFlag = true;
  304.     ::GlobalUnlock(cbhdl);
  305.   }
  306. }
  307.  
  308. void
  309. TODListView::CmEditDelete()
  310. {
  311.   int count = GetCount();
  312.   int index = GetSelIndex();
  313.   if (count <= 1 || index >= count-1)
  314.     return;
  315.  
  316.   ODItemInfo item;
  317.   item.Hdc = ::GetDC(*this);
  318.   item.Index = index;
  319.   item.Data  = (void far*)GetItemData(index);
  320.   item.State = 0;
  321.   GetItemInfo(item);
  322.   ::ReleaseDC(*this, item.Hdc);
  323.   if (item.Extent.cx == MaxWidth)
  324.     SetHorizontalExtent(MaxWidth = 0); // force recalculate max width
  325.   if (!(Attr.Style & LBS_HASSTRINGS))  // strings not stored in list box
  326.     delete item.Data;
  327.  
  328.   DeleteString(index);
  329.   SetSelIndex(index);
  330.   DirtyFlag = true;
  331. }
  332.  
  333. void
  334. TODListView::CmEditClear()
  335. {
  336.   int count = GetCount();
  337.   if (count == 1)
  338.     return;
  339.   if (count) {
  340.     if (!(Attr.Style & LBS_HASSTRINGS))  // strings not stored in list box
  341.       for (int index = 0; index < count-1; index++)
  342.         delete[] (char far*)GetItemData(index);
  343.     ClearList();
  344.     DirtyFlag = true;
  345.     SetHorizontalExtent(MaxWidth = 0);
  346.   }
  347.   AddString(VirtualLastLineStr);
  348. }
  349.  
  350. TODListView::~TODListView()
  351. {
  352.   if (GetHandle())
  353.     CmEditClear();
  354. }
  355.  
  356. void
  357. TODListView::EvDestroy()
  358. {
  359.   CmEditClear();
  360.   TWindow::EvDestroy();
  361. }
  362.  
  363. static int linePrompt(TWindow* parent, int index, uint id, char far* buf,int buflen)
  364. {
  365.   char msg[41];
  366.   sprintf(msg, string(*parent->GetModule(), IDS_ODLISTNUM).c_str(), index);
  367.   const char far* prompt = string(*parent->GetModule(), id).c_str();
  368.   return TInputDialog(parent, msg, prompt, buf, buflen).Execute();
  369. }
  370.  
  371. void
  372. TODListView::CmEditAdd()
  373. {
  374.   char inputText[80];
  375.   *inputText = 0;
  376.  
  377.   int index = GetSelIndex();
  378.   if (index < 0)
  379.     index = 0;
  380.  
  381.   if (linePrompt(this,index+1,CM_ODLISTADD,inputText,sizeof(inputText))==IDOK) {
  382.     char far* str;
  383.     if (Attr.Style & LBS_HASSTRINGS) {   // strings stored in list box
  384.       str = inputText;
  385.     }
  386.     else {
  387.       str = new char[strlen(inputText)+1];
  388.       strcpy(str, inputText);
  389.     }
  390.     InsertString(str, index);
  391.     SetSelIndex(index+1);
  392.     DirtyFlag = true;
  393.   }
  394. }
  395.  
  396. void
  397. TODListView::CmEditItem()
  398. {
  399.   int index = GetSelIndex();
  400.   if (index < 0 || index >= GetCount()-1)
  401.     return;
  402.  
  403.   int len;
  404.   char* inputText;
  405.   if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
  406.     len = GetStringLen(index);
  407.     inputText = new char[len + 81];
  408.     GetString(inputText, index);
  409.   }
  410.   else {
  411.     char far* str = (char far*)GetItemData(index);
  412.     len = strlen(str);
  413.     inputText = new char[len + 81];
  414.     strcpy(inputText, str);
  415.   }
  416.   if (linePrompt(this,index+1,CM_ODLISTEDIT,inputText, len + 81)==IDOK) {
  417.     char far* str;
  418.     if (Attr.Style & LBS_HASSTRINGS) {  // strings stored in list box
  419.       str = inputText;
  420.     }
  421.     else {
  422.       delete (char far*)GetItemData(index);
  423.       str = strnewdup(inputText);
  424.     }
  425.     DeleteString(index);
  426.     InsertString(str, index);
  427.     SetSelIndex(index);
  428.     DirtyFlag = true;
  429.   }
  430.   delete inputText;
  431. }
  432.  
  433. IMPLEMENT_STREAMABLE2(TODListView, TODListBox, TView);
  434.  
  435. void *
  436. TODListView::Streamer::Read(ipstream &is, uint32 /* version */) const
  437. {
  438.   ReadBaseObject((TODListBox*)GetObject(), is);
  439.   ReadBaseObject((TView*)GetObject(), is);
  440.   is >> GetObject()->Origin;
  441.   GetObject()->DirtyFlag = false;
  442.   return GetObject();
  443. }
  444.  
  445. void
  446. TODListView::Streamer::Write(opstream &os) const
  447. {
  448.   WriteBaseObject((TODListBox*)GetObject(), os);
  449.   WriteBaseObject((TView*)GetObject(), os);
  450.   os << GetObject()->Origin;
  451. }
  452.